﻿using IBatisNet.DataAccess.Interfaces;
using IBatisNet.DataAccess;
using System.Collections.Generic;
using IBatisNet.DataMapper;
using IBatisNet.DataAccess.DaoSessionHandlers;
using IBatisNet.DataMapper.SessionStore;
using IBatisNet.Common;
using IBatisNet.DataMapper.MappedStatements;
using IBatisNet.DataMapper.Scope;
using System.Data;
using curbside.IBatis.Common;
using System.Data.SqlClient;
using IBatisNet.Common.Transaction;
using System;
using IBatisNet.DataMapper.Configuration.ParameterMapping;
using System.Linq;

namespace curbside.IBatis
{
    public class BaseDAO : IDao
    {
        /// <summary>
        /// 得到数据库操作上下文
        /// </summary>
        /// <returns></returns>
        public IDalSession GetContext
        {
            get
            {
                return CurrentDaoManager.LocalDaoSession;
            }
        }

        public IDaoManager CurrentDaoManager
        {
            get
            {
                return DaoManager.GetInstance(this);
            }
        }

        /// <summary>
        /// 得到SqlMap DAO SesionHandler
        /// </summary>
        protected ISqlMapper sqlMap
        {
            get
            {
                ISqlMapper _sqlMapper = (GetContext as SqlMapDaoSession).SqlMap;

                //设置ISqlMapper的存储方式
                _sqlMapper.SessionStore = new HybridWebThreadSessionStore(_sqlMapper.Id);
                return _sqlMapper;
            }
        }

        /// <summary>
        /// 向数据库插入记录
        /// </summary>
        /// <param name="statementName">要执行的sql statement</param>
        /// <param name="parames">查询参数</param>
        /// <returns></returns>
        public object Insert(string statementName, object parames)
        {
            return sqlMap.Insert(statementName, parames);
        }

        /// <summary>
        /// 向表中批量插入数据
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public void BatchInsert(DataTable dt, string tableName)
        {
            BatchInsert(dt, tableName, 200);
        }

        /// <summary>
        /// 向表中批量插入数据
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public void BatchInsert(DataTable dt, string tableName, int batchSize)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                using (SqlBulkCopy sbc = new SqlBulkCopy(GetContext.Connection.ConnectionString))
                {
                    sbc.BatchSize = batchSize;
                    sbc.DestinationTableName = tableName;

                    sbc.WriteToServer(dt);
                }

                scope.Complete();
            }
        }

        /// <summary>
        /// 更新数据库的记录
        /// </summary>
        /// <param name="statementName">要执行的sql statement</param>
        /// <param name="parames">查询参数</param>
        /// <returns></returns>
        public int Update(string statementName, object parames)
        {
            return sqlMap.Update(statementName, parames);
        }

        public int BatchUpdate(DataTable dt, string tableName)
        {
            using (SqlDataAdapter adapter = new SqlDataAdapter("", GetContext.Connection.ConnectionString))
            {
                adapter.Update(dt);
            }

            return 0;
        }

        /// <summary>
        /// 删除数据库的记录
        /// </summary>
        /// <param name="statementName">要执行的sql statement</param>
        /// <param name="parames">查询参数</param>
        /// <returns></returns>
        public int Delete(string statementName, object parames)
        {
            return sqlMap.Delete(statementName, parames);
        }

        /// <summary>
        /// 根据给定的sql语句名称和相关参数对象查询出相关的内容
        /// </summary>
        /// <param name="statementName">要执行的sql statement</param>
        /// <param name="parames">查询参数</param>
        /// <returns></returns>
        public object QueryForObject(string statementName, object parames)
        {
            return sqlMap.QueryForObject(statementName, parames);
        }

        /// <summary>
        /// 根据给定的sql语句名称和相关参数对象查询出相关的内容的列表
        /// </summary>
        /// <typeparam name="T">查询对象类型</typeparam>
        /// <param name="statementName">要执行的sql statement</param>
        /// <param name="parames">查询参数</param>
        /// <returns></returns>
        public IList<T> QueryForList<T>(string statementName, object parames)
        {
            return sqlMap.QueryForList<T>(statementName, parames);
        }

        /// <summary>
        /// 得到执行的sql语句
        /// </summary>
        /// <param name="statementName">要执行的sql statement</param>
        /// <param name="paramObject">查询参数</param>
        /// <returns></returns>
        public string GetSqlStatement(string statementName, object paramObject)
        {
            IMappedStatement statement = sqlMap.GetMappedStatement(statementName);
            if (!sqlMap.IsSessionStarted)
            {
                sqlMap.OpenConnection();
            }

            RequestScope scope = statement.Statement.Sql.GetRequestScope(statement, paramObject, sqlMap.LocalSession);
            return scope.PreparedStatement.PreparedSql;
        }

        /// <summary>
        /// 根据给定的sql语句名称和相关参数对象查询出相关内容到DataSet
        /// </summary>
        /// <param name="statementName">要执行的sql statement</param>
        /// <param name="paramObject">查询参数</param>
        /// <returns></returns>
        public DataSet QueryForDataSet(string statementName, object paramObject)
        {
            DataSet ds = new DataSet();
            IMappedStatement statement = sqlMap.GetMappedStatement(statementName);
            if (!sqlMap.IsSessionStarted)
            {
                sqlMap.OpenConnection();
            }

            RequestScope scope = statement.Statement.Sql.GetRequestScope(statement, paramObject, sqlMap.LocalSession);
            statement.PreparedCommand.Create(scope, sqlMap.LocalSession, statement.Statement, paramObject);

            //备份参数
            var paramList = new List<IDbDataParameter>();
            foreach (IDbDataParameter para in scope.IDbCommand.Parameters)
                paramList.Add(para);
            scope.IDbCommand.Parameters.Clear();

            IDbCommand dc = sqlMap.LocalSession.CreateCommand(scope.IDbCommand.CommandType);
            dc.CommandText = scope.IDbCommand.CommandText;
            foreach (var para in paramList)
                dc.Parameters.Add(para);
            IDbDataAdapter dda = sqlMap.LocalSession.CreateDataAdapter(dc);
            dda.Fill(ds);
            
            if (scope.ParameterMap != null)
            {
                //处理返回参数
                string parameterPrefix = ((((IBatisNet.DataMapper.SqlMapper)(sqlMap)).DataSource).DbProvider).ParameterPrefix;
                var properties = scope.ParameterMap.PropertiesList;

                foreach (var item in paramList)
                {
                    if (item.Direction == ParameterDirection.Output || item.Direction == ParameterDirection.InputOutput)
                    {
                        for (int i = 0; i < properties.Count; i++)
                        {
                            ParameterProperty p = properties[i];
                            string parameterName = item.ParameterName.Substring(parameterPrefix.Length);
                            if (string.Compare(p.ColumnName, parameterName, true) == 0)
                                scope.ParameterMap.SetOutputParameter(ref paramObject, p, item.Value);
                        }
                    }
                }
            }

            return ds;
        }
    }
}
